<?php
/* vim: set expandtab tabstop=2 shiftwidth=2 softtabstop=2 textwidth=150 number: */

/**
 * Funções úteis.
 *
 * ...
 *
 * PHP versão 5
 *
 * LICENÇA: Este arquivo fonte esta sob o termos da licença MIT.
 *
 * @package   scuf.util
 * @author    Rodrigo Casara <rodrigocasara@gmail.com>
 * @copyright 2012 Rodrigo Casara
 * @license   MIT License (http://www.opensource.org/licenses/mit-license.php)
 * @version   SVN: $Id$
 * @link
 * @since     SCUF(tm) v 1.0.0
 */

/**
 * Classe com métodos úteis
 *
 * PHP 5
 *
 * Scuf: Exemplo de Aplicação
 * Copyright 2012, Rodrigo Casara.
 *
 * Licenciado sob a Licença MIT
 * Redistribuições de arquivos devem manter o aviso de copyright acima.
 *
 * @copyright     Copyright 2012, Rodrigo Casara.
 * @author        Rodrigo Casara <rodrigocasara@gmail.com>
 * @package       Scuf.Lib
 * @since         Scuf v 1.0.0
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 */
class Utils {

  /**
   * Formata nome próprio com iniciais em maiúsculo; artigos e preposições em
   * minúsculo.
   *
   * <p>Exemplos de nomes formatados:</p>
   * <ul>
   * 	 <li>Rodrigo Casara</li>
   * 	 <li>João da Silva</li>
   * 	 <li>Pedro de Alcântara</li>
   * 	 <li>Maria do Patrocínio</li>
   * 	 <li>Manoela dos Santos Lima</li>
   * </ul>
   *
   * @param string $nome Nome próprio para ser formatado.
   * @param array $artigos_e_preposicoes Array com lista de artigos e preposições.
   * @return String Nome próprio formatado.
   */
  public function formatarNomeProprio($nome, $artigos_e_preposicoes = array('da', 'das', 'de', 'do', 'dos', 'a', 'e', 'o')) {
    $palavras = explode(' ', mb_convert_case($nome, MB_CASE_LOWER));
    $nomeFormatado = array();
    foreach ($palavras as $palavra) {
      if (!in_array($palavra, $artigos_e_preposicoes)) {
        $palavra = mb_convert_case($palavra, MB_CASE_TITLE);
      }
      array_push($nomeFormatado, $palavra);
    }
    return join(' ', $nomeFormatado);
  }

  /**
   * Aplica a função array_map em todas as chaves de um array.
   * Retirado de: http://www.php.net/manual/pt_BR/function.array-map.php#107690

   * @param callback $callback Função callback para executar para cada chave do array.
   * @param array $array Um array para percorrer chamando a função callback.
   * @param array $args Variável lista de argumentos array para percorrer chamando a função callback.
   * @return array Retorna um array contendo todas as chaves do array de entrada, depois de ter aplicado a função de callback para cada uma.
   */
  public function array_map_keys($callback, $array /* [, $args ..] */) {
    $args = func_get_args();
    if (! is_callable($callback)) trigger_error('first argument (callback) is not a valid function', E_USER_ERROR);
    if (! is_array($array)) trigger_error('second argument must be an array', E_USER_ERROR);
    $args[1] = array_keys($array);
    // If any additional arguments are not arrays, assume that value is wanted for every $array item.
    // array_map() will pad shorter arrays with Null values
    for ($i = 2; $i < count($args); $i++) {
      if (!is_array($args[$i])) {
        $args[$i] = array_fill(0, count($array), $args[$i]);
      }
    }
    return array_combine(call_user_func_array('array_map', $args), $array);
  }

  /**
   * Descreva o método aqui ...
   * @param mixed $valor
   * @param boolean $prefixo_binario
   * @throws Exception
   */
  public function obterTamanhoEmBytes($valor, $prefixo_binario = true) {
    if (!is_bool($prefixo_binario)) {
      $prefixo_binario = true;
    }
    $base = ($prefixo_binario ? 2 : 10);
    $expoentes = array(
      // Prefixo binário (IEC) {{{
      true => array(
        'y' => 80,	// yottabyte (YiB)
        'z' => 70,	// zettabyte (ZiB)
        'e' => 60,	// exabyte (EiB)
        'p' => 50,	// petabyte (PiB)
        't' => 40,	// terabyte (TiB)
        'g' => 30,	// gigabyte (GiB)
        'm' => 20,	// megabyte (MiB)
        'k' => 10,	// quilobyte (KiB)
        'b' => 0		// byte (B)
      ),
      //}}}
      // Sistema internacional de medidas {{{
      false => array(
        'y' => 24,	// yottabyte (YiB)
        'z' => 21,	// zettabyte (ZiB)
        'e' => 18,	// exabyte (EiB)
        'p' => 15,	// petabyte (PiB)
        't' => 12,	// terabyte (TiB)
        'g' => 9,		// gigabyte (GiB)
        'm' => 6,		// megabyte (MiB)
        'k' => 3,		// quilobyte (KiB)
        'b' => 0		// byte (B)
      ),
      //}}}
    );

    $valor = trim($valor);
    $unidade = trim(strtolower(substr($valor, -1)), '0123456789');
    if (strlen($unidade) == 0) {
      $unidade = "b";
    }
    if (array_key_exists($unidade, $expoentes[$prefixo_binario])) {
      $valor = $valor * pow($base, $expoentes[$prefixo_binario][$unidade]);
    } else {
      throw new Exception('Unidade desconhecida.');
    }

    return $valor;
  }

  /**
   * Converte um tamanho em bytes para um formato inteligível para humanos (por exemplo, 1KB 234MB 2GB).
   *
   * @param integer $valor Tamanho em bytes.
   * @return string Retorna uma string com o tamanho em um formato inteligível para humanos.
   */
  public function bytesParaTamanhoInteligivel($valor) {
    // Valores para o prefixo binário (IEC) {{{
    $base = 2;
    $expoentes = array(
      'y' => 80, // yottabyte (YiB)
      'z' => 70, // zettabyte (ZiB)
      'e' => 60, // exabyte (EiB)
      'p' => 50, // petabyte (PiB)
      't' => 40, // terabyte (TiB)
      'g' => 30, // gigabyte (GiB)
      'm' => 20, // megabyte (MiB)
      'k' => 10, // quilobyte (KiB)
      'b' => 0   // byte (B)
    );
    //}}

    // Converte para um tamanho mais inteligível para humanos {{{
    $unidade = 'b';
    $unidades = array_keys($expoentes);
    $i = 7;
    while ($valor >= (1024 * pow($base, $expoentes[$unidade]))) {
      $unidade = $unidades[$i--];
    }
    $valor = $valor / pow($base, $expoentes[$unidade]);
    //}}}

    // Formata o tamanho com a unidade de medida {{{
    if ($unidade === 'b') {
      $unidade = ($valor > 1) ? 'bytes' : 'byte';
    } else {
      $unidade = strtoupper($unidade) . 'B';
    }
    $valor = sprintf("%0.0f %s", $valor, $unidade);
    //}}}

    return $valor;
  }

  /**
   * Descreva o método aqui ...
   * @param string $dmy
   * @return string
   */
  public function converterDataDMYParaSQL($dmy = null) {
    $dataSQL = null;
    if ($dmy !== null) {
      // Converte a data para Y-d-m
      $data = preg_replace('/(\d{2})\/(\d{2})\/(\d{4})/', '${3}-${2}-${1}', $dmy);
      // Testa se é uma data válida {{{
      $unixTimeStamp = strtotime($data);
      if ($unixTimeStamp) {
        $dataSQL = date('Y-m-d', $unixTimeStamp);
      }
      //}}}
    }
    return $dataSQL;
  }

  /**
   * Converte um tempo no formato "HH:MM:SS" (usado no inglês) para o formato do
   * Sistema Internacional de Medidas (SI).
   *
   * Os símbolos das unidades de tempo hora (h), minuto (m) e segundo (s) são
   * escritas com um espaço entre o valor medido e o símbolo. Também há um espaço
   * entre o símbolo da unidade de tempo e o valor numérico seguinte.
   *
   *                                8 h 35 min 20 s
   *                                 | |  |   |  |
   *                          espaços de até um caractere
   *
   * Mais exemplos:
   *
   *  ENTRADA     RETORNO
   *  00:00:00    0 s
   *  17:00:00    17 h
   *  03:00:28    3 h 28 s
   *  23:59:00    23 h 59 min
   *  00:01:46    1 min 46 s
   *  00:02:04    2 min 4 s
   *  00:00:19    19 s
   *  00:00:07    7 s
   *  01:01:32    1 h 1 min 32 s
   *  00:00:29    29 s
   *  01:35:23    1 h 35 min 23 s
   *  00:29:50    29 min 50 s
   * 150:12:47    150 h 12 min 47 s
   *
   * @param string $tempo Tempo no formato "HH:MM:SS".
   * @return string Retorna uma string com o tempo no formato "0h 0min 0s".
   */
  public function abreviarTempo($tempo) {
    list($horas, $minutos, $segundos) = explode(':', $tempo);
    $resultado = array();
    if ((int)$horas > 0) {
      $resultado[] = sprintf("%d h", (int)$horas);
    }
    if ((int)$minutos > 0) {
      $resultado[] = sprintf("%d min", (int)$minutos);
    }
    if ((int)$segundos > 0 || (!(int)$horas) > 0 && !(int)$minutos > 0) {
      $resultado[] = sprintf("%d s", (int)$segundos);
    }
    return implode(' ', $resultado);
  }

}
?>